/*     */ package com.zimbra.cs.session;
/*     */ 
/*     */ import com.zimbra.common.stats.RealtimeStatsCallback;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.LogFactory;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.stats.ZimbraPerf;
/*     */ import com.zimbra.cs.util.Zimbra;
/*     */ import java.util.ArrayList;
/*     */ import java.util.Collection;
/*     */ import java.util.HashMap;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import java.util.Random;
/*     */ import java.util.Timer;
/*     */ import java.util.TimerTask;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public final class SessionCache
/*     */ {
/*     */   private static final String sRunIdentifier;
/*     */   private static final long SESSION_SWEEP_INTERVAL_MSEC = 60000L;
/*     */   static Log sLog;
/*     */   static final SessionMap[] sSessionMaps;
/*     */   
/*     */   static String registerSession(Session session)
/*     */   {
/*  54 */     if ((sShutdown) || (session == null)) {
/*  55 */       return null;
/*     */     }
/*  57 */     Session.Type sessionType = session.getSessionType();
/*  58 */     String sessionId = session.getSessionId();
/*  59 */     assert (sessionId != null);
/*     */     
/*  61 */     getSessionMap(sessionType).putAndPrune(session.getAuthenticatedAccountId(), sessionId, session, sessionType.getMaxPerAccount());
/*  62 */     return sessionId;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static Session lookup(String sessionId, String accountId)
/*     */   {
/*  74 */     if (sShutdown) {
/*  75 */       return null;
/*     */     }
/*  77 */     Session.Type type = getSessionTypeFromId(sessionId);
/*  78 */     Session s = getSessionMap(type).get(accountId, sessionId);
/*  79 */     if ((s == null) && (ZimbraLog.session.isDebugEnabled())) {
/*  80 */       ZimbraLog.session.debug("no session with id " + sessionId + " found (accountId: " + accountId + ")");
/*     */     }
/*  82 */     return s;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static Collection<Session> getSoapSessions(String accountId)
/*     */   {
/*  94 */     if (sShutdown)
/*  95 */       return null;
/*  96 */     return getSessionMap(Session.Type.SOAP).get(accountId);
/*     */   }
/*     */   
/*     */   public static Collection<Session> getAllSessions(String accountId) {
/* 100 */     if (sShutdown)
/* 101 */       return null;
/* 102 */     Collection<Session> ret = new ArrayList();
/* 103 */     for (Session.Type type : Session.Type.values()) {
/* 104 */       Collection<Session> sessions = getSessionMap(type).get(accountId);
/* 105 */       if (sessions != null) {
/* 106 */         ret.addAll(sessions);
/*     */       }
/*     */     }
/* 109 */     return ret;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   public static void clearSession(Session session)
/*     */   {
/* 117 */     Session target = unregisterSession(session);
/* 118 */     if (target == null) {
/* 119 */       return;
/*     */     }
/* 121 */     Session.Type type = target.getSessionType();
/* 122 */     if (target != null) {
/* 123 */       assert (!Thread.holdsLock(getSessionMap(type)));
/* 124 */       target.doCleanup();
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static Session unregisterSession(Session session)
/*     */   {
/* 138 */     if ((sShutdown) || (session == null) || (!session.isAddedToSessionCache())) {
/* 139 */       return null;
/*     */     }
/* 141 */     if (ZimbraLog.session.isDebugEnabled()) {
/* 142 */       ZimbraLog.session.debug("Unregistering session " + session.getSessionId());
/*     */     }
/* 144 */     Session.Type type = session.getSessionType();
/* 145 */     return getSessionMap(type).remove(session.getAuthenticatedAccountId(), session.getSessionId());
/*     */   }
/*     */   
/*     */   public static void startup()
/*     */   {
/* 150 */     Zimbra.sTimer.schedule(new SweepMapTimerTask(), 30000L, 60000L);
/* 151 */     ZimbraPerf.addStatsCallback(new StatsCallback());
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public static void shutdown()
/*     */   {
/* 158 */     sShutdown = true;
/*     */     SessionMap sessionMap;
/* 160 */     for (sessionMap : sSessionMaps) {
/* 161 */       List<Session> list = sessionMap.pruneSessionsByTime(Long.MAX_VALUE);
/*     */       
/*     */ 
/*     */ 
/*     */ 
/* 166 */       for (Session s : list) {
/* 167 */         assert (!Thread.holdsLock(sessionMap));
/* 168 */         s.doCleanup();
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   static String qualifySessionId(String sessionId)
/*     */   {
/* 176 */     return sRunIdentifier + "." + sessionId;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private static final Session.Type getSessionTypeFromId(String sessionId)
/*     */   {
/* 189 */     if ((sessionId == null) || (sessionId.length() < 2)) {
/* 190 */       return Session.Type.NULL;
/*     */     }
/* 192 */     return Session.Type.values()[Character.digit(sessionId.charAt(0), 10)];
/*     */   }
/*     */   
/*     */   static
/*     */   {
/* 173 */     sRunIdentifier = System.currentTimeMillis() / 1000L + "." + new Random().nextInt(100);
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 186 */     sLog = LogFactory.getLog(SessionCache.class);
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 197 */     sSessionMaps = new SessionMap[Session.Type.values().length];
/* 198 */     for (Session.Type type : Session.Type.values()) {
/* 199 */       sSessionMaps[type.getIndex()] = new SessionMap(type);
/*     */     }
/*     */   }
/*     */   
/*     */   private static final SessionMap getSessionMap(Session.Type type) {
/* 204 */     return sSessionMaps[type.getIndex()];
/*     */   }
/*     */   
/*     */ 
/* 208 */   private static boolean sShutdown = false;
/*     */   
/*     */ 
/* 211 */   private static long sContextSeqNo = 1L;
/*     */   
/*     */   static synchronized String getNextSessionId(Session.Type type) {
/* 214 */     return Integer.toString(type.getIndex()) + Long.toString(sContextSeqNo++);
/*     */   }
/*     */   
/*     */   static void logActiveSessions() {
/* 218 */     StringBuilder accountList = new StringBuilder();
/* 219 */     StringBuilder manySessionsList = new StringBuilder();
/* 220 */     int totalSessions = 0;
/* 221 */     int totalAccounts = 0;
/*     */     
/* 223 */     int[] sessionTypeCounter = new int[Session.Type.values().length];
/*     */     
/* 225 */     for (SessionMap sessionMap : sSessionMaps) {
/* 226 */       synchronized (sessionMap) {
/* 227 */         for (SessionMap.AccountSessionMap activeAcct : sessionMap.activeAccounts()) {
/* 228 */           String accountId = null;
/* 229 */           totalAccounts++;
/* 230 */           int count = 0;
/* 231 */           for (Session session : activeAcct.values()) {
/* 232 */             accountId = session.getAuthenticatedAccountId();
/* 233 */             totalSessions++;
/* 234 */             count++;
/* 235 */             sessionTypeCounter[sessionMap.getType().getIndex()] += 1;
/*     */           }
/* 237 */           assert (count > 0);
/* 238 */           if (count > 0) {
/* 239 */             if (accountList.length() > 0)
/* 240 */               accountList.append(',');
/* 241 */             accountList.append(accountId).append('(').append(count).append(')');
/* 242 */             if (count > 9) {
/* 243 */               if (manySessionsList.length() > 0)
/* 244 */                 manySessionsList.append(',');
/* 245 */               manySessionsList.append(accountId).append('(').append(count).append(')');
/*     */             }
/*     */           }
/*     */         }
/*     */       }
/*     */     }
/*     */     
/* 252 */     if ((sLog.isDebugEnabled()) && (totalSessions > 0)) {
/* 253 */       sLog.debug("Detected " + totalSessions + " active sessions.  " + sessionTypeCounter + ".  Accounts: " + accountList);
/*     */     }
/*     */     
/* 256 */     if (manySessionsList.length() > 0) {
/* 257 */       ZimbraLog.session.info("Found accounts that have a large number of sessions: " + manySessionsList);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static List<Session> getActiveSessions(Session.Type type)
/*     */   {
/* 268 */     return getSessionMap(type).copySessionList();
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static int[] countActive(Session.Type type)
/*     */   {
/* 278 */     int[] toRet = new int[2];
/*     */     
/* 280 */     SessionMap sessionMap = getSessionMap(type);
/*     */     
/* 282 */     synchronized (sessionMap) {
/* 283 */       toRet[0] = sessionMap.totalActiveAccounts();
/* 284 */       toRet[1] = sessionMap.totalActiveSessions();
/*     */     }
/* 286 */     return toRet;
/*     */   }
/*     */   
/*     */ 
/*     */   private static final class StatsCallback
/*     */     implements RealtimeStatsCallback
/*     */   {
/*     */     public Map<String, Object> getStatData()
/*     */     {
/* 295 */       Map<String, Object> data = new HashMap();
/* 296 */       SessionMap soapMap = SessionCache.getSessionMap(Session.Type.SOAP);
/* 297 */       data.put("soap_sessions", Integer.valueOf(soapMap.totalActiveSessions()));
/* 298 */       return data;
/*     */     }
/*     */   }
/*     */   
/*     */   private static final class SweepMapTimerTask extends TimerTask
/*     */   {
/*     */     public void run()
/*     */     {
/*     */       try {
/* 307 */         if (SessionCache.sLog.isDebugEnabled()) {
/* 308 */           SessionCache.logActiveSessions();
/*     */         }
/* 310 */         int[] removedByType = new int[Session.Type.values().length];
/* 311 */         int totalActive = 0;
/*     */         SessionMap sessionMap;
/* 313 */         for (sessionMap : SessionCache.sSessionMaps) {
/* 314 */           List<Session> toReap = sessionMap.pruneIdleSessions();
/* 315 */           totalActive += sessionMap.totalActiveSessions();
/*     */           
/*     */ 
/* 318 */           removedByType[sessionMap.getType().getIndex()] += toReap.size();
/*     */           
/* 320 */           for (Session s : toReap) {
/* 321 */             if (ZimbraLog.session.isDebugEnabled()) {
/* 322 */               ZimbraLog.session.debug("Removing cached session: %s", new Object[] { s });
/*     */             }
/* 324 */             assert (!Thread.holdsLock(sessionMap));
/*     */             
/*     */ 
/*     */             try
/*     */             {
/* 329 */               s.doCleanup();
/*     */             }
/*     */             catch (Exception e) {
/* 332 */               ZimbraLog.session.warn("cleanup failed for session %s", new Object[] { s });
/*     */             }
/*     */           }
/*     */         }
/*     */         
/* 337 */         int totalRemoved = 0;
/* 338 */         for (int r : removedByType) {
/* 339 */           totalRemoved += r;
/*     */         }
/*     */         
/* 342 */         if ((SessionCache.sLog.isInfoEnabled()) && (totalRemoved > 0)) {
/* 343 */           StringBuilder sb = new StringBuilder("Removed ").append(totalRemoved).append(" idle sessions (");
/* 344 */           StringBuilder typeStr = new StringBuilder();
/* 345 */           for (int i = 1; i < removedByType.length; i++) {
/* 346 */             if (removedByType[i] > 0) {
/* 347 */               if (typeStr.length() > 0) {
/* 348 */                 typeStr.append(", ");
/*     */               }
/* 350 */               typeStr.append(Session.Type.values()[i].name());
/*     */             }
/*     */           }
/* 353 */           sb.append(typeStr).append("). ").append(totalActive).append(" active sessions remain.");
/* 354 */           SessionCache.sLog.info(sb.toString());
/*     */         }
/*     */       } catch (Throwable e) {
/* 357 */         if ((e instanceof OutOfMemoryError))
/* 358 */           Zimbra.halt("Caught out of memory error", e);
/* 359 */         ZimbraLog.session.warn("Caught exception in SessionCache timer", e);
/*     */       }
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/session/SessionCache.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */